package online.heycm.codegenerator.generator;

import java.io.File;
import lombok.extern.slf4j.Slf4j;
import online.heycm.codegenerator.common.jdbc.UrlTemplate;
import online.heycm.codegenerator.common.types.DBType;
import online.heycm.platform.common.entity.exception.Assert;
import org.mybatis.generator.config.CommentGeneratorConfiguration;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.Context;
import org.mybatis.generator.config.JDBCConnectionConfiguration;
import org.mybatis.generator.config.JavaClientGeneratorConfiguration;
import org.mybatis.generator.config.JavaModelGeneratorConfiguration;
import org.mybatis.generator.config.JavaTypeResolverConfiguration;
import org.mybatis.generator.config.ModelType;
import org.mybatis.generator.config.PluginConfiguration;
import org.mybatis.generator.config.SqlMapGeneratorConfiguration;
import org.mybatis.generator.config.TableConfiguration;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.util.ArrayList;
import java.util.List;
import org.springframework.util.StringUtils;

/**
 * MyBatis 代码生成器
 *
 * @author heycm
 * @since 2023/12/17 19:52
 */
@Slf4j
public class MyBatisGenerator {

    public static void main(String[] args) {
        GeneratorSetting setting = new GeneratorSetting();
        setting.setDriverClass(DBType.MySQL.getDriver());
        setting.setUrl(
                "jdbc:mysql://localhost:3306/yizhou?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=UTC");
        setting.setUsername("root");
        setting.setPassword("root123");
        ArrayList<String> tables = new ArrayList<>();
        tables.add("pay_account");
        setting.setTables(tables);

        setting.setParentPackage("com.weiwei.code");
        setting.setAuthor("这个是作者");
        setting.setOutput("C:\\Users\\hey\\Desktop\\code-generator");
        generate(setting);
    }

    public static boolean generate(GeneratorSetting setting) {
        File dir = new File(setting.getOutput());
        if (!dir.exists()) {
            boolean mkdirs = dir.mkdirs();
            Assert.isTrue(mkdirs, "创建文件目录失败");
        }
        try {
            // 数据库配置
            Configuration config = new Configuration();
            config.addContext(getContext(setting));
            // 文件覆盖
            DefaultShellCallback callback = new DefaultShellCallback(true);
            // 告警信息
            List<String> warnings = new ArrayList<String>();
            new org.mybatis.generator.api.MyBatisGenerator(config, callback, warnings).generate(null);
            return true;
        } catch (Exception e) {
            log.error("MyBatis 代码生成器执行异常", e);
        }
        return false;
    }

    private static Context getContext(GeneratorSetting setting) {
        Context context = new Context(ModelType.CONDITIONAL);
        context.setId("mybatis");
        context.setTargetRuntime("MyBatis3Simple");

        // Context 的 <property> 属性
        // 当表名或者字段名为SQL关键字时，自动加分隔符
        context.addProperty("autoDelimitKeywords", "true");
        context.addProperty("beginningDelimiter", "`");
        context.addProperty("endingDelimiter", "`");

        // 配置连接
        JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
        jdbcConnectionConfiguration.setDriverClass(setting.getDriverClass());
        jdbcConnectionConfiguration.setConnectionURL(setting.getUrl());
        jdbcConnectionConfiguration.setUserId(setting.getUsername());
        jdbcConnectionConfiguration.setPassword(setting.getPassword());
        context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);
        // 配置指定JDBC类型和Java类型转换
        JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration();
        javaTypeResolverConfiguration.addProperty("forceBigDecimals", "false");
        context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration);
        // 配置如何生成注释信息
        CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration();
        commentGeneratorConfiguration.setConfigurationType("online.heycm.codegenerator.generator.MyBatisCommentGenerator");
        commentGeneratorConfiguration.addProperty("author", StringUtils.hasText(setting.getAuthor()) ? setting.getAuthor() : "MBG");
        // commentGeneratorConfiguration.addProperty("suppressAllComments", "true");
        // commentGeneratorConfiguration.addProperty("suppressDate", "true");
        // commentGeneratorConfiguration.addProperty("addRemarkComments", "true");
        // commentGeneratorConfiguration.addProperty("dateFormat", "yyyy-MM-dd");
        context.setCommentGeneratorConfiguration(commentGeneratorConfiguration);
        // 配置Mapper接口
        JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
        javaClientGeneratorConfiguration.setTargetPackage(setting.getParentPackage());
        javaClientGeneratorConfiguration.setTargetProject(setting.getOutput());
        javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
        context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
        // 配置Mapper.xml
        SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
        sqlMapGeneratorConfiguration.setTargetPackage(setting.getParentPackage());
        sqlMapGeneratorConfiguration.setTargetProject(setting.getOutput());
        context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);
        // 配置实体类
        JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
        javaModelGeneratorConfiguration.setTargetPackage(setting.getParentPackage());
        javaModelGeneratorConfiguration.setTargetProject(setting.getOutput());
        context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);
        // 配置生成表
        for (String table : setting.getTables()) {
            TableConfiguration tc = new TableConfiguration(new Context(ModelType.CONDITIONAL));
            tc.setTableName(table);
            context.addTableConfiguration(tc);
        }
        // 插件
        // 生成实体类实现 Serializable 接口
        PluginConfiguration serializablePlugin = new PluginConfiguration();
        serializablePlugin.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
        context.addPluginConfiguration(serializablePlugin);
        // 生成实体类 toString 方法
        PluginConfiguration toStringPlugin = new PluginConfiguration();
        toStringPlugin.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
        context.addPluginConfiguration(toStringPlugin);
        // 新生成覆盖 XML 文件
        PluginConfiguration unmergeableXmlMappersPlugin = new PluginConfiguration();
        unmergeableXmlMappersPlugin.setConfigurationType("org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin");
        context.addPluginConfiguration(unmergeableXmlMappersPlugin);
        return context;
    }
}
